#pragma once

#include <Windows.h>
#include <winternl.h>
#include <windef.h>
#include <stdint.h>
#include <xmmintrin.h>


typedef unsigned __int64 QWORD;

enum DCOMPOSITION_COMMAND_ID
{
    ProcessCommandBufferIterator, // 0, size = 0x18
    ActiveChannelTrigger, // 1, size = 0x8
    CreateResource, // 2, size = 0x10
    OpenSharedResource, // 3, size = 0x18
    ReleaseResource, // 4, size = 0x8
    SetChannelIntegerProperty, // 5, size = 0x10
    GetAnimationTime, // 6, size = 0x18
    CapturePointer, // 7, size = 0x18
    ActivateResourceTrigger, // 8, size = 0xc
    OpenSharedResourceHandle, // 9, size = 0x10
    SetResourceCallbackId, // 10, size = 0xc
    SetResourceIntegerProperty, // 11, size = 0x18
    SetResourceFloatProperty, // 12, size = 0x10
    SetResourceHandleProperty, // 13, size = 0x18
    SetResourceHandleArrayProperty, // 14, size = 0x10 + (8 * n of handles)
    SetResourceBufferProperty, // 15, size = 0x10 + ((BufferSize + 3) &0xfffffffc)
    SetResourceReferenceProperty, // 16, size = 0x10
    SetResourceReferenceArrayProperty, // 17, size = 0x10 + (4 * n of reference resources)
    SetResourceAnimationProperty, // 18, size = 0x10
    SetResourceDeletedNotificationTag, // 19, size = 0x10
    AddVisualChild, // 20, size = 0x14
    RedirectMouseToHwnd, // 21, size = 0x48
    SetVisualInputSink, // 22, size = 0x10
    RemoveVisualChild, // 23, size = 0xc
};

#pragma pack(push, 1)

typedef struct {
    DCOMPOSITION_COMMAND_ID CmdId;
    DWORD InternalCmdId; // 0x4
    VOID* CommandBufferPtr; // 0x8
    DWORD CommandBufferSize; // 0x10
    DWORD Padding; // 0x14
} PROCESS_COMMAND_BUFFER_ITERATOR; // 0

typedef struct {
    DCOMPOSITION_COMMAND_ID CmdId;
    DWORD Mode; // 0x4
} ACTIVE_CHANNEL_TRIGGER; // 1

typedef struct {
    DCOMPOSITION_COMMAND_ID CmdId;
    DWORD ResourceId;    // 0x4
    DWORD ResourceType; // 0x8
    DWORD IsSharedResource; // 0xc, 1 = Shared, 0 = Private
} CREATE_RESOURCE; // 2

typedef struct {
    DCOMPOSITION_COMMAND_ID CmdId;
    DWORD ResourceId; // 0x4
    HANDLE ResourceHandle; // 0x8
    DWORD ResourceType; // 0x10
    DWORD OpenMode; // 0x14, 1 = Write, 2 = Read
} OPEN_SHARED_RESOURCE; // 3

typedef struct {
    DCOMPOSITION_COMMAND_ID CmdId;
    DWORD ResourceId; // 0x4
} RELEASE_RESOURCE; // 4

typedef struct {
    DCOMPOSITION_COMMAND_ID CmdId;
    int PropertyType; // 0x4
    __int64 I64Value;    // 0x8
} SET_CHANNEL_INTEGER_PROPERTY; // 5

typedef struct {
    DCOMPOSITION_COMMAND_ID CmdId;
    DWORD ResourceId; // 0x4
    QWORD Unknown; // 0x8
    __int64 AnimationTime; // 0x10, this is only used to get animation time back
} GET_ANIMATION_TIME; // 6

typedef struct {
    DCOMPOSITION_COMMAND_ID CmdId;
    DWORD ResourceId; // 0x4
    DWORD AddRequired; // 0x8, 1 = Add
    DWORD PointerId; // 0xc
    __int64 Reserved; // 0x10
} CAPTURE_POINTER; // 7

typedef struct {
    DCOMPOSITION_COMMAND_ID CmdId;
    DWORD ResourceId; // 0x4
    DWORD Mode;    // 0x8
} ACTIVATE_RESOURCE_TRIGGER; // 8

typedef struct {
    DCOMPOSITION_COMMAND_ID CmdId;
    DWORD ResourceId; // 0x4
    PHANDLE OpenedHandlePtr; // 0x8
} OPEN_SHARED_RESOURCE_HANDLE; // 9

typedef struct {
    DCOMPOSITION_COMMAND_ID CmdId;
    DWORD ResourceId; // 0x4
    DWORD CallbackId; // 0x8
} SET_RESOURCE_CALLBACK_ID; // 10

typedef struct {
    DCOMPOSITION_COMMAND_ID CmdId;
    DWORD ResourceId; // 0x4
    DWORD PropertyType; // 0x8
    __int64 I64Value; // 0x10
} SET_RESOURCE_INTEGER_PROPERTY; // 11

typedef struct {
    DCOMPOSITION_COMMAND_ID CmdId;
    DWORD ResourceId; // 0x4
    DWORD PropertyType; // 0x8
    DWORD FValue; // 0xc
} SET_RESOURCE_FLOAT_PROPERTY; // 12

typedef struct {
    DCOMPOSITION_COMMAND_ID CmdId;
    DWORD ResourceId; // 0x4
    DWORD PropertyId; // 0x8
    HANDLE Handle; // 0x10
} SET_RESOURCE_HANDLE_PROPERTY; // 13

typedef struct {
    DCOMPOSITION_COMMAND_ID CmdId;
    DWORD ResourceId; // 0x4
    DWORD PropertyType; // 0x8, must be 3 (others are not implemented)
    DWORD NumHandles; // 0xc
    HANDLE HandleArray[]; // 0x10
} SET_RESOURCE_HANDLE_ARRAY_PROPERTY; // 14

typedef struct {
    DCOMPOSITION_COMMAND_ID CmdId;
    DWORD ResourceId; // 0x4
    DWORD PropertyId; // 0x8
    DWORD BufferSize; // 0xc
    BYTE Buffer[]; // 0x10
} SET_RESOURCE_BUFFER_PROPERTY; // 15

typedef struct {
    DCOMPOSITION_COMMAND_ID CmdId;
    DWORD ResourceId; // 0x4
    DWORD PropertyId; // 0x8
    DWORD ReferenceResourceId; // 0xc            
} SET_RESOURCE_REFERENCE_PROPERTY; // 16

typedef struct {
    DCOMPOSITION_COMMAND_ID CmdId;
    DWORD ResourceId; // 0x4
    DWORD PropertyType; // 0x8
    DWORD NumReferenceResources; // 0xc
    DWORD ReferenceResourceIdArray; // 0x10
} SET_RESOURCE_REFERENCE_ARRAY_PROPERTY; // 17

typedef struct {
    DCOMPOSITION_COMMAND_ID CmdId;
    DWORD ResourceId; // 0x4
    DWORD PropertyType; // 0x8
    DWORD AnimationResourceId; // 0xc
} SET_RESOURCE_ANIMATION_PROPERTY; // 18

typedef struct {
    DCOMPOSITION_COMMAND_ID CmdId;
    DWORD ResourceId; // 0x4
    PVOID TagPtr; // 0x8
} SET_RESOURCE_DELETED_NOTIFICATION_TAG; // 19

typedef struct {
    DCOMPOSITION_COMMAND_ID CmdId;
    DWORD ResourceId; // 0x4
    DWORD ChildResourceId; // 0x8
    DWORD InsertAbove; // 0xc
    DWORD ReferenceResourceId; // 0x10
} ADD_VISUAL_CHILD; // 20

typedef struct {
    DCOMPOSITION_COMMAND_ID CmdId;
    DWORD ResourceId; // 0x4
    HWND TargetHwnd; // 0x8
    int Flag1; // 0x10
    DWORD Flag2; // 0x14
    DWORD RoutingInfoExist; // 0x18, 1 = Exist
    struct {
        __m128 Unknown1; // 0x20
        __m128 Unknown2; // 0x28
        __m128 Unknown3; // 0x38
    } TagMsgRoutingInfo;
} REDIRECT_MOUSE_TO_HWND; // 21

typedef struct {
    DCOMPOSITION_COMMAND_ID CmdId;
    DWORD ResourceId; // 0x4
    HANDLE InputSinkHandle; // 0x8
} SET_VISUAL_INPUT_SINK; // 22

typedef struct {
    DCOMPOSITION_COMMAND_ID CmdId;
    DWORD ResourceId; // 0x4
    DWORD ChildResourceId; // 0x8
} REMOVE_VISUAL_CHILD; // 23

#pragma pack(pop)

typedef NTSTATUS(*pNtDCompositionCreateChannel)(
    OUT PHANDLE hChannel,
    IN OUT PSIZE_T pSectionSize,
    OUT PVOID* pMappedAddress
    );

typedef NTSTATUS(*pNtDCompositionProcessChannelBatchBuffer)(
    IN HANDLE hChannel,
    IN DWORD dwArgStart,
    OUT PDWORD pOutArg1,
    OUT PDWORD pOutArg2
    );


typedef NTSTATUS(*pNtDCompositionCommitChannel)(
    IN HANDLE hChannel,
    OUT PDWORD out1,
    OUT PDWORD out2,
    IN DWORD flag,
    IN HANDLE Object
    );

typedef NTSTATUS(*pNtDCompositionDestroyChannel)(
    IN HANDLE hChannel
    );


